package com.ganyu.service.impl;

import com.alibaba.excel.util.StringUtils;
import com.ganyu.component.RedisCache;
import com.ganyu.domain.LoginUser;
import com.ganyu.domain.ResponseResult;
import com.ganyu.domain.entity.User;
import com.ganyu.domain.vo.BlogUserLoginVo;
import com.ganyu.domain.vo.UserInfoVo;
import com.ganyu.exception.SystemException;
import com.ganyu.mapper.UserMapper;
import com.ganyu.service.UserLoginService;
import com.ganyu.utils.BeanCopyUtils;
import com.ganyu.utils.JwtUtil;

import com.ganyu.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.Objects;

import static com.ganyu.enums.AppHttpCodeEnum.*;


/**
 * DATA: 2022/9/15
 * Author: 晨夕
 */
@Service
public class UserLoginServiceImpl implements UserLoginService {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private UserMapper userMapper;

    @Autowired

    private PasswordEncoder passwordEncoder;
    @Override
    public ResponseResult<User> login(User user) {
        //1.用户未输入用户名或密码，提醒用户
        if(StringUtils.isEmpty(user.getUserName())){
            throw new SystemException(REQUIRE_USERNAME);
        }
        if(StringUtils.isEmpty(user.getPassword())){
            throw new SystemException(REQUIRE_PASSWORD);
        }
        //用户不存在，提醒
        User user1 = userMapper.selectUserName(user.getUserName());
        if(ObjectUtils.isEmpty(user1)){
            throw new SystemException(USERNAME_ERROR);
        }
        //密码输入有误，提醒
        String password = userMapper.selectPassword(user.getUserName());
        boolean matches = passwordEncoder.matches(user.getPassword(), password);
        if(!matches){
            throw new SystemException(PASSWORD_ERROR);
        }
        //2.调用ProviderManager的方法进行认证 如果认证通过生成jwt
        //2.1 进行认证
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUserName(), user.getPassword());
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        //2.2判断是否认证成功
        if(Objects.isNull(authenticate)){
            throw new RuntimeException("用户不存在或密码错误");
        }
        //2.3 认证成功后，获取authenticate中的用户主体信息
        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
        //2.4 获取用户id，生成jwt
        String userId = loginUser.getUser().getId().toString();
        String token = JwtUtil.createJWT(userId);
        //3.把用户信息存入redis中
        redisCache.setCacheObject("userId:" + userId ,loginUser);
        //4.返回给前台特定的数据
        UserInfoVo userInfoVo = BeanCopyUtils.copyBean(loginUser.getUser(), UserInfoVo.class);
        BlogUserLoginVo blogUserLoginVo = new BlogUserLoginVo(token, userInfoVo);
        return ResponseResult.okResult(blogUserLoginVo);
    }

    @Override
    public ResponseResult<User> logout() {
        //1. 获取userId
        Long id = SecurityUtils.getUserId();
        //2. 根据userId删除redis中的用户信息
        redisCache.deleteObject("userId:" + id);
        return ResponseResult.okResult(SUCCESS);
    }
}
